package br.unifor.cct.mia.select;

import br.unifor.cct.mia.evolutionary.Genotype;
import br.unifor.cct.mia.ga.Ga;
import br.unifor.cct.mia.util.Methods;

public class MinimizeRoulette implements Select {
    private Genotype[] newPopulation;    
    
    public Object execute(Object value) {
    	Object[] o = (Object[])value;
		Ga Ga = (Ga)o[0];
		
        newPopulation = new Genotype[Ga.configurations.getPopsize()];
        return roulette(Ga);
    }
    
    private Genotype[] roulette(Ga Ga){
    	if ( Ga.population[Ga.configurations.getPopsize()] != null ) {//Ja adiciona o melhor
    		newPopulation[Ga.configurations.getPopsize()] = (Genotype)Ga.population[Ga.configurations.getPopsize()].clone();    		
    		newPopulation[0] = (Genotype)Ga.population[Ga.configurations.getPopsize()].clone();
    	}
    	
    	double fitMin[] = new double[Ga.configurations.getPopsize()];
    	double sum = 0.0, sumProb = 0.0;

    	for (int mem = 0; mem < Ga.configurations.getPopsize(); mem++) {
        	fitMin[mem] = ((Genotype)Ga.population[mem]).getFitnessMin() + 
        		Math.abs(((Genotype)Ga.population[Ga.configurations.getPopsize()]).getFitnessMin()); 
        		
        	sum += fitMin[mem]; 
        }

        for (int mem = 0; mem < Ga.configurations.getPopsize(); mem++) {
        	if (sum == 0) ((Genotype)Ga.population[mem]).setSelectProbability(1);
        	else ((Genotype)Ga.population[mem]).setSelectProbability(Math.abs(fitMin[mem] / sum));
            
        	sumProb += ((Genotype)Ga.population[mem]).getSelectProbability();
        }
                       
		double min = 0, max = 0, p = 0;

        for (int i = 0; i < Ga.configurations.getPopsize(); i++) {
        	p = Methods.randDoubleValue(0, sumProb);        	
        	min=0;
        	max=0;	                	
        	
        	for (int j = 0; j < Ga.configurations.getPopsize(); j++) {        		
	        	max += ((Genotype)Ga.population[j]).getSelectProbability();
	  			
	        	if ( (p >= min) && (p < max) ){
	  				newPopulation[i] = (Genotype)((Genotype)Ga.population[j]).clone();
	  				break;
	  			} 
	  			
	        	min = max;
        	}
        }
        
        System.arraycopy(newPopulation, 0, Ga.population, 0, Ga.configurations.getPopsize()-1);
        
        return (Genotype[])Ga.population;
    }
}
